#include "head.h"
#include "process_command.h"
#define BIGFILE 100000000

//olx——ls
void listFilesAndSend(int sockfd, const char *directoryPath);



// 处理cd命令，即更新路径名
int cd_work(client_info_t *client_info)
{
    // 先接收路径
    train_t train;
    memset(&train, 0, sizeof(train));
    recv(client_info->net_fd, &train.len, sizeof(int), MSG_WAITALL);
    recv(client_info->net_fd, train.data, train.len, MSG_WAITALL);


    if(strcmp(train.data,".")==0){
        //当前目录不做操作
    printf("逻辑路径：%s\n", client_info->virtual_global_path);
    printf("真实路径：%s\n", client_info->global_path);
    }
    else{
        if(strcmp(train.data,"..")==0){
     if(strcmp(train.data,"..")==0) {
            // 退回上级目录
            // 找到当前路径中第一个斜杠的位置
            char *ptr = client_info->virtual_global_path;
            char *second_last_slash = NULL;
            char *last_slash = NULL;
            while (*ptr != '\0') {
                if (*ptr == '/') {
                    second_last_slash = last_slash;
                    last_slash = ptr;
                }
                ptr++;
            }
            if (second_last_slash != NULL) {
                // 将倒数第二个斜杠之后的部分截断
                *(second_last_slash + 1) = '\0';
            }

            // 同样地，也更新真实路径
            ptr = client_info->global_path;
            second_last_slash = NULL;
            last_slash = NULL;
            while (*ptr != '\0') {
                if (*ptr == '/') {
                    second_last_slash = last_slash;
                    last_slash = ptr;
                }
                ptr++;
            }
            if (second_last_slash != NULL) {
                // 将倒数第二个斜杠之后的部分截断
                *(second_last_slash + 1) = '\0';
            }
        printf("逻辑路径：%s\n", client_info->virtual_global_path);
        printf("真实路径：%s\n", client_info->global_path);
}
    }else{
        // 更新客户端的虚拟路径和真实路径
    strcat(client_info->virtual_global_path, train.data);
    strcat(client_info->virtual_global_path, "/");
    strcat(client_info->global_path, train.data);
    strcat(client_info->global_path, "/");
     // 测试代码
    printf("逻辑路径：%s\n", client_info->virtual_global_path);
    printf("真实路径：%s\n", client_info->global_path);
    }
    }
    
    return 0;
}

// 处理ls命令，即展示当前目录下所有文件     --功能还没完善，这里ls不能把.和..也显示出来
int ls_work(const client_info_t *client_info)
{
    char currentDir[1024];
    strcpy(currentDir, client_info->global_path);
    printf("%s\n",currentDir);
    listFilesAndSend((*client_info).net_fd,currentDir);//调用listFilesAndSend.c进行遍历文件目录，遍历的过程中发送
    return 0;
}

// 处理pwd命令，即传输虚拟path
int pwd_work(const client_info_t *client_info)
{

    char p[1024] = {0};
    strcpy(p, client_info->virtual_global_path);

    int len = strlen(p);  // 获取字符串长度

    if (len > 0) {
        p[len - 1] = '\0';  // 将最后一个字符替换为字符串结束符
    }

    len = strlen(p);
    send(client_info->net_fd, &len, sizeof(int), MSG_NOSIGNAL);
    send(client_info->net_fd, p, len, MSG_NOSIGNAL);

    return 0;
}

// 处理remove命令，即删除文件   --集文
int remove_work(const client_info_t const *client_info)
{

    // 先接收路径
    train_t train;
    memset(&train, 0, sizeof(train));
    recv(client_info->net_fd, &train.len, sizeof(int), MSG_WAITALL);
    recv(client_info->net_fd, train.data, train.len, MSG_WAITALL);

    char path[1024] = {0};
    strcpy(path, client_info->global_path);
    strcat(path, train.data);

    printf("要删除的路径是：%s\n", path);


    if (remove(path) == 0){
        printf("File deleted successfully.\n");
    }
    else{
        printf("Error deleting file.\n");
    }

    //strcat(client_info->global_path, "/");
    
    return 0;
}

// 处理puts命令，即接收文件
int puts_work(const client_info_t *client_info)
{

    printf("1\n");
    // 用来接收返回值检错的
    ssize_t recv_bytes;

    // 接收文件名（路径）
    char path[1024] = {0};
    int path_len;
    recv_bytes = recv(client_info->net_fd, &path_len, sizeof(int), MSG_WAITALL);
    ERROR_CHECK(recv_bytes, -1, "recv path_len");
    recv_bytes = recv(client_info->net_fd, path, path_len, MSG_WAITALL);
    ERROR_CHECK(recv_bytes, -1, "recv path_name");
    
    char file_name[1024];
    int i;
    for(i = path_len - 1; i > 0; i--){
        if(path[i] == '/'){
            //路径从后往前的第一个'/'
            break;
        }
    }
    if(i){
        //把从后往前第一个'/'后面的内容赋值给file_name
        strcpy(file_name, (path + i + 1));     
    }else{
        // i==0,意味path存的就是个文件名
        strcpy(file_name, path);
    }

    printf("要创建的文件名为: %s\n",file_name);
    
    char absolute_path[1024] = {0};
    strcpy(absolute_path, client_info->global_path);
    strcat(absolute_path, file_name);

    printf("要创建的文件路径为: %s\n",absolute_path);
    
    // 创建文件
    int file_fd = open(absolute_path, O_RDWR | O_CREAT, 0666);
    ERROR_CHECK(file_fd, -1, "open");

    // 读取文件的长度
    off_t file_size;
    recv_bytes = recv(client_info->net_fd, &file_size, sizeof(off_t), MSG_WAITALL);
    ERROR_CHECK(recv_bytes, -1, "recv file_size");
    printf("%ld\n", file_size);

    // 读取客户端传过来的内容，并且写入文件
    train_t train;
    memset(&train, 0, sizeof(train));
    while (1)
    {
        recv(client_info->net_fd, &train.len, sizeof(int), MSG_WAITALL);
        if (0 == train.len)
        {
            // 对方发送完毕
            break;
        }
        recv_bytes = recv(client_info->net_fd, train.data, train.len, MSG_WAITALL);
        ERROR_CHECK(recv_bytes, -1, "recv train.data");
        recv_bytes = write(file_fd, train.data, recv_bytes);
        ERROR_CHECK(recv_bytes, -1, "write");
    }

    close(file_fd);

    return 0;
}

// 处理gets命令，即发送文件
int gets_work(const client_info_t *client_info)
{

    // 用来接收返回值检错的
    ssize_t sent_bytes;

    // 接收文件名
    char file_name[1024] = {0};
    int file_name_len;
    recv(client_info->net_fd, &file_name_len, sizeof(int), MSG_WAITALL);
    recv(client_info->net_fd, file_name, file_name_len, MSG_WAITALL);

    
    char path[1024]; 
    if('/' == file_name[0]){
        //这是个绝对路径，拼接逻辑路径
        strcpy(path, client_info->virtual_global_path);
        strcat(path,file_name);
    }else{
        //这是个相对路径，拼接真实路径
        strcpy(path, client_info->global_path);
        strcat(path, file_name);
    }

    printf("绝对路径为%s\n",path);

    // 打开文件
    int file_fd = open(path, O_RDONLY);
    ERROR_CHECK(file_fd, -1, "open");

    // 获得整个文件的大小，给客户端发送文件大小
    struct stat st;
    fstat(file_fd, &st);
    sent_bytes = send(client_info->net_fd, &st.st_size, sizeof(st.st_size), MSG_NOSIGNAL);
    ERROR_CHECK(sent_bytes, -1, "send st.st_size");
    train_t train; // “小火车”
    // 开始发送文件内容
    if (st.st_size > BIGFILE)
    {
        // 大文件传输，用sendfile性能更好
        sent_bytes = sendfile(client_info->net_fd, file_fd, NULL, st.st_size);
        ERROR_CHECK(sent_bytes, -1, "sendfile");
    }
    else
    {
        // 小文件传输，用while+send性能更好
        while (1)
        {
            // 读取文件
            memset(train.data, 0, sizeof(train.data));
            train.len = read(file_fd, train.data, sizeof(train.data));
            if (train.len == 0)
            {
                // 文件读完了
                break;
            }
            // 发送文件
            // 先发长度
            sent_bytes = send(client_info->net_fd, &train.len, sizeof(train.len), MSG_NOSIGNAL);
            ERROR_CHECK(sent_bytes, -1, "send train.len");
            // 再发数据
            sent_bytes = send(client_info->net_fd, train.data, train.len, MSG_NOSIGNAL);
            ERROR_CHECK(sent_bytes, -1, "send train.data");
        }
    }

    // 这里还要有个发送结束了的标识
    train.len = 0;
    sent_bytes = send(client_info->net_fd, &train, sizeof(train), MSG_NOSIGNAL);
    ERROR_CHECK(sent_bytes, -1, "send overflag");

    // 关闭文件
    close(file_fd);

    return 0;
}


//  listFilesAndSend.c
//  函数用于列出指定目录下的所有文件和目录，并将文件名发送给客户端
void listFilesAndSend(int sockfd, const char *directoryPath)
{
    DIR *dir = opendir(directoryPath);
    printf("1\n");
    if (dir == NULL)
    {
        perror("Unable to open directory");
        return;
    }

    char all_dirname[1024] = {0};
    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL)
    {
        strcat(all_dirname, entry->d_name);
        strcat(all_dirname,"/");
        
    }
    int len = strlen(all_dirname);  // 获取字符串长度

    if (len > 0) {
        all_dirname[len - 1] = '\0';  // 将最后一个字符替换为字符串结束符
    }


    printf("%s\n",all_dirname);

    train_t train;
    memset(&train, 0, sizeof(train));
    train.len = strlen(all_dirname);
    memcpy(train.data, all_dirname, strlen(all_dirname));
    send(sockfd, &train, sizeof(train.len) + train.len, MSG_NOSIGNAL);

    if (closedir(dir) == -1)
    {
        perror("Error closing directory");
    }
}
